from db.base import DBClient
import psycopg2
import logging


class PostgreSQLDBClient(DBClient):
    def __init__(self, conf: dict):
        if conf is None:
            raise ValueError('The arg conf cannot bt None.')
        if not isinstance(conf, dict):
            raise TypeError('The type of arg conf must be dict, but %s' % type(conf))
        for key in ['host', 'port', 'user', 'password', 'database']:
            if key not in conf.keys():
                raise KeyError('The dict conf must contain key %s' % key)
        self.conf = conf
        self.conn = None
        self.cursor = None

    def open(self, *args, **kwargs):
        self.conn = psycopg2.connect(**self.conf)
        self.cursor = self.conn.cursor()

    def close(self, *args, **kwargs):
        if self.conn is not None:
            self.conn.close()

    def query(self, *args, **kwargs):
        select_after = '*' if len(args) == 0 else ', '.join(args)
        if not kwargs['FROM']:
            raise RuntimeError('Plz provide an kwarg "from" or the value you supplied is empty.')

        sql = 'SELECT %s FROM %s' % (select_after, kwargs['FROM'])

        where_after = kwargs.get('WHERE', '')
        if where_after:
            sql += ' WHERE %s' % where_after

        group_by_after = kwargs.get('GROUP_BY', '')
        if group_by_after:
            sql += ' GROUP BY %s' % group_by_after

        having_after = kwargs.get('HAVING', '')
        if having_after:
            sql += ' HAVING %s' % having_after

        order_by_after = kwargs.get('ORDER_BY', '')
        if order_by_after:
            sql += ' ORDER BY %s' % order_by_after

        limit_after = kwargs.get('LIMIT', '')
        if limit_after:
            sql += ' LIMIT %s' % limit_after

        logging.info('sql: %s' % sql)
        self.cursor.execute(sql)
        return self.cursor.fetchall()

    def insert(self, *args, **kwargs):
        raise RuntimeError('An unsupported operation.')

    def insert_many(self, *args, **kwargs):
        raise RuntimeError('An unsupported operation.')

    def delete(self, *args, **kwargs):
        raise RuntimeError('An unsupported operation.')

    def delete_many(self, *args, **kwargs):
        raise RuntimeError('An unsupported operation.')

    def update(self, *args, **kwargs):
        raise RuntimeError('An unsupported operation.')

    def update_many(self, *args, **kwargs):
        raise RuntimeError('An unsupported operation.')

    def execute(self, *args, **kwargs):
        raise RuntimeError('An unsupported operation.')
